//
//  LVPullToRefreshAnimator.m
//  Live
//
//  Created by RoyLei on 16/7/14.
//  Copyright © 2016年 Heller. All rights reserved.
//

#import "LVPullToRefreshAnimator.h"

static const NSUInteger KeyframeCount = 60;

@implementation LVPullToRefreshAnimator

// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) + 1
CGFloat LVAElasticEaseOut(CGFloat p)
{
    return sin(-13 * M_PI_2 * (p + 1)) * pow(2, -10 * p) + 1;
}

+ (CAPropertyAnimation *)scaleAnimation:(CFTimeInterval)duration {
    CABasicAnimation * anim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    anim.duration = duration;
    anim.fromValue = @(1.0);
    anim.toValue = @(0.25);
    anim.repeatCount = HUGE;
    anim.autoreverses = YES;
    anim.fillMode = kCAFillModeForwards;
    anim.removedOnCompletion = NO;
    
    return anim;
}

+ (CAPropertyAnimation *)opacityAnimation:(CFTimeInterval)duration {
    CABasicAnimation * anim = [CABasicAnimation animationWithKeyPath:@"opacity"];
    anim.duration = duration;
    anim.fromValue = @(0.0);
    anim.toValue = @(1.0);
    anim.repeatCount = 0;
    anim.removedOnCompletion = NO;
    anim.fillMode = kCAFillModeForwards;
    
    return anim;
}

+ (CAPropertyAnimation *)scalePathAnimation:(CFTimeInterval)duration startPath:(UIBezierPath *)startPath endPath:(UIBezierPath *)endPath {
    CABasicAnimation * anim = [CABasicAnimation animationWithKeyPath:@"path"];
    anim.duration = duration;
    anim.repeatCount = 0;
    anim.fromValue = (id)startPath.CGPath;
    anim.toValue = (id)endPath.CGPath;
    anim.removedOnCompletion = NO;
    anim.fillMode = kCAFillModeForwards;
    
    return anim;
}

+ (CAAnimationGroup *)groupScaleLayerAnimation:(CFTimeInterval)duration {
    
    CABasicAnimation * opacityAnim = (CABasicAnimation *)[LVPullToRefreshAnimator opacityAnimation:duration];
    opacityAnim.beginTime = 0;
    opacityAnim.repeatCount = HUGE;
    opacityAnim.autoreverses = YES;
    opacityAnim.fromValue = @1.0f;
    opacityAnim.toValue = @0.0f;
    
    CAPropertyAnimation * scaleAnim = [LVPullToRefreshAnimator scaleAnimation:duration];
    scaleAnim.beginTime = 0;
    
    CAAnimationGroup *group = [CAAnimationGroup animation];
    group.animations = @[opacityAnim, scaleAnim];
    group.duration = duration;
    group.repeatCount = HUGE;
    group.autoreverses = YES;
    group.fillMode = kCAFillModeForwards;
    group.removedOnCompletion = NO;
    group.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    
    return group;
}

+ (CABasicAnimation*)repeatRotateAnimation {
    
    
    NSTimeInterval animationDuration = 1;
    CAMediaTimingFunction *linearCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    animation.fromValue = 0;
    animation.toValue = [NSNumber numberWithFloat:M_PI*2];
    animation.duration = animationDuration;
    animation.timingFunction = linearCurve;
    animation.removedOnCompletion = NO;
    animation.repeatCount = INFINITY;
    animation.fillMode = kCAFillModeForwards;
    animation.autoreverses = NO;
    
    return animation;
    
}

+ (CAKeyframeAnimation *)popAnimation {
    
    CATransform3D fromMatrix = CATransform3DMakeScale(0.0, 0.0, 0.0);
    CATransform3D toMatrix = CATransform3DMakeScale(1.0f, 1.0f, 1.0f);
    CAKeyframeAnimation *animation = [LVPullToRefreshAnimator animationWithCATransform3DForKeyPath:@"transform"
                                                                                     easingFunction:LVAElasticEaseOut
                                                                                         fromMatrix:fromMatrix
                                                                                           toMatrix:toMatrix];
    animation.duration = 1.0f;
    animation.removedOnCompletion = NO;
    
    return animation;
    
}

+(CAKeyframeAnimation *)animationWithCATransform3DForKeyPath:(NSString *)keyPath
                                              easingFunction:(LVViewEasingFunctionPointerType)function
                                                  fromMatrix:(CATransform3D)fromMatrix
                                                    toMatrix:(CATransform3D)toMatrix {
    
    NSMutableArray *values = [NSMutableArray arrayWithCapacity:KeyframeCount];
    
    CGFloat t = 0.0;
    CGFloat dt = 1.0 / (KeyframeCount - 1);
    
    for(size_t frame = 0; frame < KeyframeCount; ++frame, t += dt) {
        
        CATransform3D value;
        
        value.m11 = fromMatrix.m11 + function(t) * (toMatrix.m11 - fromMatrix.m11);
        value.m12 = fromMatrix.m12 + function(t) * (toMatrix.m12 - fromMatrix.m12);
        value.m13 = fromMatrix.m13 + function(t) * (toMatrix.m13 - fromMatrix.m13);
        value.m14 = fromMatrix.m14 + function(t) * (toMatrix.m14 - fromMatrix.m14);
        
        value.m21 = fromMatrix.m21 + function(t) * (toMatrix.m21 - fromMatrix.m21);
        value.m22 = fromMatrix.m22 + function(t) * (toMatrix.m22 - fromMatrix.m22);
        value.m23 = fromMatrix.m23 + function(t) * (toMatrix.m23 - fromMatrix.m23);
        value.m24 = fromMatrix.m24 + function(t) * (toMatrix.m24 - fromMatrix.m24);
        
        value.m31 = fromMatrix.m31 + function(t) * (toMatrix.m31 - fromMatrix.m31);
        value.m32 = fromMatrix.m32 + function(t) * (toMatrix.m32 - fromMatrix.m32);
        value.m33 = fromMatrix.m33 + function(t) * (toMatrix.m33 - fromMatrix.m33);
        value.m34 = fromMatrix.m34 + function(t) * (toMatrix.m34 - fromMatrix.m34);
        
        value.m41 = fromMatrix.m41 + function(t) * (toMatrix.m41 - fromMatrix.m41);
        value.m42 = fromMatrix.m42 + function(t) * (toMatrix.m42 - fromMatrix.m42);
        value.m43 = fromMatrix.m43 + function(t) * (toMatrix.m43 - fromMatrix.m43);
        value.m44 = fromMatrix.m44 + function(t) * (toMatrix.m44 - fromMatrix.m44);
        
        [values addObject:[NSValue valueWithCATransform3D:value]];
        
    }
    
    CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:keyPath];
    [animation setValues:values];
    
    return animation;
}


@end
